package com.gec.anan.driver.service.impl;

import com.gec.anan.common.constant.SystemConstant;
import com.gec.anan.common.execption.AnanException;
import com.gec.anan.common.result.ResultCodeEnum;
import com.gec.anan.common.util.LocationUtil;
import com.gec.anan.dispatch.client.NewOrderFeignClient;
import com.gec.anan.driver.service.OrderService;
import com.gec.anan.map.client.LocationFeignClient;
import com.gec.anan.map.client.MapFeignClient;
import com.gec.anan.model.entity.order.OrderInfo;
import com.gec.anan.model.enums.OrderStatus;
import com.gec.anan.model.form.map.CalculateDrivingLineForm;
import com.gec.anan.model.form.order.OrderFeeForm;
import com.gec.anan.model.form.order.StartDriveForm;
import com.gec.anan.model.form.order.UpdateOrderBillForm;
import com.gec.anan.model.form.order.UpdateOrderCartForm;
import com.gec.anan.model.form.rules.FeeRuleRequestForm;
import com.gec.anan.model.form.rules.ProfitsharingRuleRequestForm;
import com.gec.anan.model.form.rules.RewardRuleRequestForm;
import com.gec.anan.model.vo.base.PageVo;
import com.gec.anan.model.vo.map.DrivingLineVo;
import com.gec.anan.model.vo.map.OrderLocationVo;
import com.gec.anan.model.vo.map.OrderServiceLastLocationVo;
import com.gec.anan.model.vo.order.*;
import com.gec.anan.model.vo.rules.FeeRuleResponseVo;
import com.gec.anan.model.vo.rules.ProfitsharingRuleResponseVo;
import com.gec.anan.model.vo.rules.RewardRuleResponseVo;
import com.gec.anan.order.client.OrderInfoFeignClient;
import com.gec.anan.rules.client.FeeRuleFeignClient;
import com.gec.anan.rules.client.ProfitsharingRuleFeignClient;
import com.gec.anan.rules.client.RewardRuleFeignClient;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.CompletableFuture;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderInfoFeignClient orderInfoFeignClient;
    @Autowired
    private NewOrderFeignClient newOrderFeignClient;
    @Autowired
    private MapFeignClient mapFeignClient;
    @Autowired
    private LocationFeignClient locationFeignClient;
    @Autowired
    private ProfitsharingRuleFeignClient profitsharingRuleFeignClient;
    @Autowired
    private FeeRuleFeignClient feeRuleFeignClient;
    @Autowired
    private RewardRuleFeignClient rewardRuleFeignClient;

    //结束代驾
    @Override
    @SneakyThrows
    public Boolean endDrive(OrderFeeForm orderFeeForm) {
        //1 根据订单id获取订单详情，判断司机是否接单
        //异步执行
        CompletableFuture<OrderInfo> orderInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            OrderInfo orderInfo = orderInfoFeignClient.getOrderInfo(orderFeeForm.getOrderId()).getData();
            if (orderInfo.getDriverId() != orderFeeForm.getDriverId()) {
                throw new AnanException(ResultCodeEnum.ILLEGAL_REQUEST);
            }
            return orderInfo;
        });

        //计算是否到达乘客位置，防止刷单
        CompletableFuture<OrderServiceLastLocationVo> lastLocationVoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            OrderServiceLastLocationVo lastLocationVo = locationFeignClient.getOrderServiceLastLocation(orderFeeForm.getOrderId()).getData();
            return lastLocationVo;
        });
        //合并前面两个线程
        CompletableFuture.allOf(orderInfoCompletableFuture, lastLocationVoCompletableFuture)
                .join();
        //等待这两个线程执行完
        //获取前面两个线程结果
        OrderInfo orderInfo = orderInfoCompletableFuture.get();
        OrderServiceLastLocationVo lastLocationVo = lastLocationVoCompletableFuture.get();
        double distance = LocationUtil.getDistance(orderInfo.getStartPointLatitude().doubleValue()
                , orderInfo.getStartPointLongitude().doubleValue()
                , lastLocationVo.getLatitude().doubleValue(), lastLocationVo.getLongitude().doubleValue());
        if (distance > SystemConstant.DRIVER_END_LOCATION_DISTION) {
            throw new AnanException(ResultCodeEnum.DRIVER_END_LOCATION_DISTION_ERROR);
        }
        //2 计算实际路程
        CompletableFuture<BigDecimal> realDistanceCompletableFuture = CompletableFuture.supplyAsync(() -> {
            BigDecimal realDistance = locationFeignClient.calculateOrderRealDistance(orderFeeForm.getOrderId()).getData();
            return realDistance;
        });
        //3 计算实际代驾费用
        CompletableFuture<FeeRuleResponseVo> ruleResponseVoCompletableFuture =
                realDistanceCompletableFuture.thenApplyAsync((realDistance) -> {
//封装FeeRuleRequestForm信息
            FeeRuleRequestForm ruleRequestForm = new FeeRuleRequestForm();
            ruleRequestForm.setDistance(realDistance);
            ruleRequestForm.setStartTime(orderInfo.getStartServiceTime());
            //计算乘客等待时间
            Integer waitMinute = Math.abs((int) (orderInfo.getAcceptTime().getTime() - orderInfo.getArriveTime().getTime()) / (1000 * 60));
            ruleRequestForm.setWaitMinute(waitMinute);
            FeeRuleResponseVo ruleResponseVo = feeRuleFeignClient.calculateOrderFee(ruleRequestForm).getData();
            //订单总金额 需加上 路桥费、停车费、其他费用、乘客好处费
            BigDecimal totalAmount = ruleResponseVo.getTotalAmount()
                    .add(orderFeeForm.getOtherFee())
                    .add(ruleResponseVo.getWaitFee())
                    .add(orderInfo.getFavourFee())
                    .add(orderFeeForm.getParkingFee())
                    .add(orderFeeForm.getTollFee());
            ruleResponseVo.setTotalAmount(totalAmount);
            return ruleResponseVo;
        });
        //4计算系统奖励
        CompletableFuture<Long> orderNumCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //计算时间内订单数与封装参数
            String startTime = new DateTime(orderInfo.getStartServiceTime()).toString("yyyy-MM-dd") + " 00:00:00";
            String endTime = new DateTime(orderInfo.getStartServiceTime()).toString("yyyy-MM-dd") + " 23:59:59";
            Long orderNum = orderInfoFeignClient.getOrderNumByTime(startTime, endTime).getData();
            return orderNum;
        });
        CompletableFuture<RewardRuleResponseVo> rewardRuleResponseVoCompletableFuture = orderNumCompletableFuture.thenApplyAsync((orderNum) -> {
            RewardRuleRequestForm rewardRuleRequestForm = new RewardRuleRequestForm();
            rewardRuleRequestForm.setOrderNum(orderNum);
            rewardRuleRequestForm.setStartTime(orderInfo.getStartServiceTime());
            RewardRuleResponseVo rewardRuleResponseVo = rewardRuleFeignClient.calculateOrderRewardFee(rewardRuleRequestForm).getData();
            return rewardRuleResponseVo;
        });

        //5 计算分账信息
        CompletableFuture<ProfitsharingRuleResponseVo> profitsharingRuleResponseVoCompletableFuture = ruleResponseVoCompletableFuture.thenCombineAsync(orderNumCompletableFuture
                , (ruleResponseVo, orderNum) -> {
                    ProfitsharingRuleRequestForm profitsharingRuleRequestForm = new ProfitsharingRuleRequestForm();
                    profitsharingRuleRequestForm.setOrderNum(orderNum);
                    profitsharingRuleRequestForm.setOrderAmount(ruleResponseVo.getTotalAmount());
                    ProfitsharingRuleResponseVo profitsharingRuleResponseVo = profitsharingRuleFeignClient.calculateOrderProfitsharingFee(profitsharingRuleRequestForm).getData();
                    return profitsharingRuleResponseVo;
                });

        //合并所有的线程
        CompletableFuture.allOf(
                orderInfoCompletableFuture,
                realDistanceCompletableFuture,
                ruleResponseVoCompletableFuture,
                rewardRuleResponseVoCompletableFuture,
                profitsharingRuleResponseVoCompletableFuture,
                orderNumCompletableFuture
        ).join();
        //获取执行结果
        BigDecimal realDistance = realDistanceCompletableFuture.get();
        FeeRuleResponseVo ruleResponseVo = ruleResponseVoCompletableFuture.get();
        RewardRuleResponseVo rewardRuleResponseVo = rewardRuleResponseVoCompletableFuture.get();
        ProfitsharingRuleResponseVo profitsharingRuleResponseVo = profitsharingRuleResponseVoCompletableFuture.get();
        //封装实体类，添加分账信息与账单信息
        UpdateOrderBillForm updateOrderBillForm = new UpdateOrderBillForm();
        updateOrderBillForm.setOrderId(orderFeeForm.getOrderId());
        updateOrderBillForm.setDriverId(orderFeeForm.getDriverId());
        //路桥费、停车费、其他费用
        updateOrderBillForm.setTollFee(orderFeeForm.getTollFee());
        updateOrderBillForm.setParkingFee(orderFeeForm.getParkingFee());
        updateOrderBillForm.setOtherFee(orderFeeForm.getOtherFee());
        //乘客好处费
        updateOrderBillForm.setFavourFee(orderInfo.getFavourFee());

        //实际里程
        updateOrderBillForm.setRealDistance(realDistance);
        //订单奖励信息
        BeanUtils.copyProperties(rewardRuleResponseVo, updateOrderBillForm);
        //代驾费用信息
        BeanUtils.copyProperties(ruleResponseVo, updateOrderBillForm);

        //分账相关信息
        BeanUtils.copyProperties(profitsharingRuleResponseVo, updateOrderBillForm);
        updateOrderBillForm.setProfitsharingRuleId(profitsharingRuleResponseVo.getProfitsharingRuleId());

        orderInfoFeignClient.endDrive(updateOrderBillForm);
        return true;
    }
    //查询司机订单
    @Override
    public PageVo findDriverOrderPage(Long driverId, Long page, Long limit) {
        return orderInfoFeignClient.findDriverOrderPage(driverId,page,limit).getData();
    }
   //司机推送支付订单
    @Override
    public Boolean sendOrderBillInfo(Long orderId, Long driverId) {
        return orderInfoFeignClient.sendOrderBillInfo(orderId,driverId).getData();
    }

    /**
     * 查询订单状态
     *
     * @param orderId
     * @return
     */
    @Override
    public Integer getOrderStatus(Long orderId) {
        Integer orderStatus = orderInfoFeignClient.getOrderStatus(orderId).getData();
        if (orderStatus == null) {
            throw new AnanException(ResultCodeEnum.FEIGN_FAIL);
        }
        return orderStatus;
    }

    /**
     * 查询司机新订单数据
     *
     * @param userId
     * @return
     */
    @Override
    public List<NewOrderDataVo> findNewOrderQueueData(Long userId) {
        return newOrderFeignClient.findNewOrderQueueData(userId).getData();
    }

    /**
     * 司机抢单
     *
     * @param driverId
     * @param orderId
     * @return
     */
    @Override
    public Boolean robNewOrder(Long driverId, Long orderId) {
        return orderInfoFeignClient.robNewOrder(driverId, orderId).getData();
    }

    /**
     * 查找当前司机的订单
     *
     * @param driverId
     * @return
     */
    @Override
    public CurrentOrderInfoVo searchDriverCurrentOrder(Long driverId) {
        return orderInfoFeignClient.searchDriverCurrentOrder(driverId).getData();
    }

    //获取订单详情
    @Override
    public OrderInfoVo getOrderInfo(Long orderId, Long driverId) {
        OrderInfo orderInfo = orderInfoFeignClient.getOrderInfo(orderId).getData();
        if (orderInfo.getDriverId().longValue() != driverId.longValue()) {
            throw new AnanException(ResultCodeEnum.ILLEGAL_REQUEST);
        }
        //分账信息和账单信息
        OrderBillVo orderBillVo = null;
        OrderProfitsharingVo profitsharingVo =null;
        if(orderInfo.getStatus() >= OrderStatus.END_SERVICE.getStatus().intValue()){
            //远程调用复制
            orderBillVo =orderInfoFeignClient.getOrderBillInfo(orderId).getData();
            profitsharingVo = orderInfoFeignClient.getOrderProfitsharing(orderId).getData();
        }
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        orderInfoVo.setOrderId(orderId);
        BeanUtils.copyProperties(orderInfo, orderInfoVo);
        orderInfoVo.setOrderProfitsharingVo(profitsharingVo);
        orderInfoVo.setOrderBillVo(orderBillVo);
        return orderInfoVo;
    }

    //计算最佳驾驶路线
    @Override
    public DrivingLineVo calculateDrivingLine(CalculateDrivingLineForm calculateDrivingLineForm) {
        return mapFeignClient.calculateDrivingLine(calculateDrivingLineForm).getData();
    }

    //更新司机到达乘客位置
    @Override
    public Boolean driverArriveStartLocation(Long orderId, Long driverId) {
        //判断是否在乘客合适距离 1公里内
        OrderInfo orderInfo = orderInfoFeignClient.getOrderInfo(orderId).getData();
        OrderLocationVo locationVo = locationFeignClient.getCacheOrderLocation(orderId).getData();
        //计算距离
        double distance = LocationUtil.getDistance(orderInfo.getStartPointLatitude().doubleValue(),
                orderInfo.getStartPointLongitude().doubleValue()
                , locationVo.getLatitude().doubleValue(), locationVo.getLongitude().doubleValue());
        if(distance> SystemConstant.DRIVER_START_LOCATION_DISTION){
            throw new AnanException(ResultCodeEnum.DRIVER_START_LOCATION_DISTION_ERROR );
        }
        return orderInfoFeignClient.driverArriveStartLocation(orderId, driverId).getData();
    }

    //更新司机车辆信息
    @Override
    public Boolean updateOrderCart(UpdateOrderCartForm updateOrderCartForm) {
        Boolean data = orderInfoFeignClient.updateOrderCart(updateOrderCartForm).getData();
        System.out.println("司机端更新车辆结果" + data);
        return data;
    }

    //开始代驾
    @Override
    public Boolean startDrive(StartDriveForm startDriveForm) {
        return orderInfoFeignClient.startDrive(startDriveForm).getData();
    }
}
